Screens & Widgets topic
Screens & Widgets
The presentation layer is organized by feature area under lib/presentation/screens/. Navigation uses GoRouter with shell routes for persistent chrome.
Routing
The route table is declared in lib/config/routes.dart. Key patterns:
- Named routes for every destination (
/,/domains,/tutor,/review,/lesson/:id,/org,/settings/:section, …). - Auth guards via a
redirectthat inspectsauthStateProvider— unauthenticated users hit/auth/login, authenticated but onboarding-incomplete users hit/onboarding/<step>. - Shell routes wrap the post-auth tree in
OrgShellScaffold, which owns the bottom nav / side rail and the AppBar. Routes that live outside the shell (auth, onboarding, lesson full-screen) declare themselves at the top level. - Deep links route into the same tree via
Uriparsing — push notifications and OAuth redirects land directly on the right screen.
Screen categories
presentation/screens/
├── admin_onboarding/ Org admin 4-step setup wizard
├── auth/ Login, signup, MFA, password reset
├── backoffice/ Platform-admin-only views
├── domains/ Curriculum domain list + detail
├── goals/ Learning goals
├── home/ Landing screen with recent activity
├── lesson/ The core learning loop (Socratic + quiz + review)
├── notes/ User notes
├── onboarding/ 5-step first-connection flow
├── org/ Organization admin screens
├── progress/ Progress dashboards (mastery, XP, streaks)
├── review/ Spaced-repetition review queue
├── settings/ User + org settings
├── setup/ BYO Supabase bootstrap (Management API)
└── tutor/ Free-form Socratic dialogue
Responsive layout
OrgShellScaffold swaps navigation primitives based on viewport width:
- < 800 px — bottom
NavigationBar(mobile / narrow web). - ≥ 800 px — side
NavigationRail(tablet / desktop / wide web).
The viewport threshold is exported as a constant so pages can mirror it for their own responsive choices.
Key reusable widgets
| Widget | Purpose |
|---|---|
web_content_frame.dart |
Centers + max-widths content on web so the app doesn't stretch across 4K screens. The most-imported widget in the codebase. |
role_gate.dart |
Conditional render based on entitlement lookups. RoleGate(roles: [Role.admin], child: …). |
notification_bell.dart |
AppBar bell icon with unread badge. Watches notificationProvider. |
app_mode_toggle.dart |
Switch between learner and admin modes (the AppBar control shown in org mode). |
Testing patterns
Widget tests live in test/presentation/ and use alchemist for golden-file comparisons (tagged golden). Integration tests (test/integration/, tagged integration) run against a local Supabase and exercise the full stack — see test/integration/ for the datasource-level test suite pattern.
Classes
- OrgShellScaffold
-
Responsive shell for admin/manager org mode. Mirrors the personal
ScaffoldWithNavBarlayout but routes to /org/:orgId/* destinations. - RoleGate
- Conditionally renders child based on the current user's org role.
- WebContentFrame
- Constrains content width on desktop while passing through on mobile.